package com.wht.sip.core.transmit.message;

import cn.hutool.core.util.StrUtil;
import com.wht.sip.core.transmit.SIPSender;
import com.wht.sip.utils.SipUtils;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.message.SIPResponse;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Managed;

import javax.sip.*;
import javax.sip.header.HeaderFactory;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.text.ParseException;
import java.util.Arrays;

/**
 * @author by HaiTao.Wang on 2025/9/15.
 */
@Slf4j
@Managed
public class SipRequestProcessorHandle {

    @Inject
    private SIPSender sipSender;

    public HeaderFactory getHeaderFactory() {
        try {
            return SipFactory.getInstance().createHeaderFactory();
        } catch (PeerUnavailableException e) {
            log.error("未处理的异常 ", e);
        }
        return null;
    }

    public MessageFactory getMessageFactory() {
        try {
            return SipFactory.getInstance().createMessageFactory();
        } catch (PeerUnavailableException e) {
            log.error("未处理的异常 ", e);
        }
        return null;
    }


    /***
     * 回复状态码
     * 100 trying
     * 200 OK
     * 400
     * 404
     */
    public SIPResponse response(SIPRequest sipRequest, int statusCode) throws SipException, InvalidArgumentException, ParseException {
        return response(sipRequest, statusCode, null);
    }

    public SIPResponse response(SIPRequest sipRequest, int statusCode, String msg) throws SipException, InvalidArgumentException, ParseException {

        if (sipRequest.getToHeader().getTag() == null) {
            sipRequest.getToHeader().setTag(SipUtils.getNewTag());
        }
        SIPResponse response = (SIPResponse) getMessageFactory().createResponse(statusCode, sipRequest);
        response.setStatusCode(statusCode);
        if (msg != null) {
            response.setReasonPhrase(msg);
        }

        if (sipRequest.getMethod().equals(Request.SUBSCRIBE)) {
            log.error("[参数不全] 2xx的SUBSCRIBE回复，必须设置Expires header");
        }

        // 发送response
        sipSender.transmitRequest(response);

        return response;
    }

    /**
     * 获取xml的根节点
     *
     * @param evt
     * @param charset
     * @return
     * @throws DocumentException
     */
    public Element getRootElement(RequestEvent evt, String charset) throws DocumentException {

        byte[] rawContent = evt.getRequest().getRawContent();
        if (evt.getRequest().getContentLength().getContentLength() == 0
                || rawContent == null
                || rawContent.length == 0
                || StrUtil.isEmpty(new String(rawContent))) {
            return null;
        }

        if (charset == null) {
            charset = "gb2312";
        }
        SAXReader reader = new SAXReader();
        reader.setEncoding(charset);
        // 对海康出现的未转义字符做处理。
        String[] destStrArray = new String[]{"&lt;","&gt;","&amp;","&apos;","&quot;"};
        // 或许可扩展兼容其他字符
        char despChar = '&';
        byte destBye = (byte) despChar;
        // 预先计算字节数组避免重复转换
        byte[][] destByteArrays = new byte[destStrArray.length][];
        for (int j = 0; j < destStrArray.length; j++) {
            destByteArrays[j] = destStrArray[j].getBytes();
        }

        ByteArrayOutputStream result = new ByteArrayOutputStream();
        for (int i = 0; i < rawContent.length; i++) {
            if (rawContent[i] == destBye) {
                boolean isValidEscape = false;
                int matchedLength = 0;

                // 检查是否为有效的转义序列
                for (byte[] destBytes : destByteArrays) {
                    if (i + destBytes.length <= rawContent.length) {
                        byte[] bytes = Arrays.copyOfRange(rawContent, i, i + destBytes.length);
                        if (Arrays.equals(bytes, destBytes)) {
                            isValidEscape = true;
                            matchedLength = destBytes.length;
                            break;
                        }
                    }
                }

                if (isValidEscape) {
                    result.write(rawContent, i, matchedLength);
                    i += matchedLength - 1;
                } else {
                    result.write(rawContent[i]);
                }
            } else {
                result.write(rawContent[i]);
            }
        }
        byte[] bytesResult = result.toByteArray();

        Document xml;
        try {
            xml = reader.read(new ByteArrayInputStream(bytesResult));
        }catch (DocumentException e) {
            log.warn("[xml解析异常]： 原文如下： \r\n{}", new String(bytesResult));
            log.warn("[xml解析异常]： 原文如下： 尝试兼容性处理");
            String[] xmlLineArray = new String(bytesResult).split("\\r?\\n");

            // 兼容海康的address字段带有<破换xml结构导致无法解析xml的问题
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : xmlLineArray) {
                if (s.startsWith("<Address")) {
                    continue;
                }
                stringBuilder.append(s);
            }
            xml = reader.read(new ByteArrayInputStream(stringBuilder.toString().getBytes()));
        }
        return xml.getRootElement();
    }

}
